#include "httpget.h"
#include <QNetworkAccessManager>
#include <QApplication>
#include <QNetworkReply>
#include <QNetworkProxy>
#include <QNetworkRequest>
#include <QFile>
#include <QDir>
#include <QTimer>
#include "settings.h"

QNetworkAccessManager* HttpGet::manager = 0;

//start download task
HttpGet::HttpGet(const QUrl &url, const QString &filename, QObject *parent) :
    QObject(parent)
{
    //Create access manager
    if (manager == 0)
        manager = new QNetworkAccessManager(qApp);

    //set proxy
    if (Settings::proxy.isEmpty())
        manager->setProxy(QNetworkProxy(QNetworkProxy::NoProxy));
    else
        manager->setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, Settings::proxy, Settings::port));

    //open file
    retry_times = 0;
    last_finished = 0;
    name = filename;
    file = new QFile(filename);
    if (!file->open(QFile::WriteOnly))
    {
        emit finished(this, true);
        delete file;
        deleteLater();
        return;
    }
    //Start request
    start(url);
}

//start a request
void HttpGet::start(const QUrl &url)
{
    prev_percentage = 0;
    QNetworkRequest request(url);
    request.setRawHeader("User-Agent", "funplayer");
    if (retry_times)
        request.setRawHeader("Range", "bytes=" + QByteArray::number(file->size()) + '-');
    reply = manager->get(request);
    connect(reply, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
    connect(reply, SIGNAL(finished()), this, SLOT(onFinished()));
    connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(onProgressChanged(qint64,qint64)));
}

void HttpGet::onFinished()
{
    if (reply->error() != QNetworkReply::NoError) //has error
    {
        if (retry_times < Settings::retryTimes)  //retry 10s later
        {
            retry_times++;
            last_finished = file->size();
            emit retryLater(this);
            QTimer::singleShot(10000, this, SLOT(retry()));
            return;
        }
        emit finished(this, true);
        reply->deleteLater();
    }

    else
    {
        //check redirect
        int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        if (status == 302) //redirect
        {
            reply->deleteLater();
            file->seek(0);
            start(QString::fromUtf8(reply->rawHeader("Location")));
            return;
        }
        else  //finished
        {
            reply->deleteLater();
            emit finished(this, false);
            deleteLater(); //task end, delete self
        }
    }

    //close file
    file->close();
    delete file;
    file = 0;
}

void HttpGet::retry()
{
    QUrl url = reply->url();
    reply->deleteLater();
    start(url);
}

void HttpGet::onReadyRead()
{
    file->write(reply->readAll());
}

void HttpGet::onProgressChanged(qint64 received, qint64 total)
{
    int percent = (last_finished + received) * 100 / (last_finished + total);
    if (percent > prev_percentage)
    {
        prev_percentage = percent;
        emit progressChanged(this, percent);
    }
}
